package com.cbs.android.component.application.activity;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.cbs.android.component.application.R;
import com.cbs.android.component.application.activity.delayedtask.DelayedTask;
import com.cbs.android.component.application.activity.delayedtask.DelayedTaskHandler;
import com.cbs.android.component.application.activity.handler.CBSActivityLifeCyclerHandler;
import com.cbs.android.component.application.activity.handler.CBSActivityResultHandler;
import com.cbs.android.component.application.activity.handler.CBSKeyEventHandler;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by broche on 9/28/15.
 */
public abstract class CBSActivity extends FragmentActivity {
    private static List<FragmentActivity> activities = new ArrayList<>();

    protected List<CBSActivityResultHandler> activityResultHandlers = new ArrayList<>();

    protected List<CBSActivityLifeCyclerHandler> resumeHandlers = new ArrayList<>();

    protected List<CBSActivityLifeCyclerHandler> startHandlers = new ArrayList<>();

    protected List<CBSActivityLifeCyclerHandler> pauseHandlers = new ArrayList<>();

    protected List<CBSActivityLifeCyclerHandler> stopHandlers = new ArrayList<>();

    protected List<CBSActivityLifeCyclerHandler> destroyHandlers = new ArrayList<>();

    protected List<CBSKeyEventHandler> keyDownHandlers = new ArrayList<>();

    protected static List<CBSActivityResultHandler> globalActivityResultHandlers = new ArrayList<>();

    protected static List<CBSActivityLifeCyclerHandler> globalResumeHandlers = new ArrayList<>();

    protected static List<CBSActivityLifeCyclerHandler> globalStartHandlers = new ArrayList<>();

    protected static List<CBSActivityLifeCyclerHandler> globalPauseHandlers = new ArrayList<>();

    protected static List<CBSActivityLifeCyclerHandler> globalStopHandlers = new ArrayList<>();

    protected static List<CBSActivityLifeCyclerHandler> globalDestroyHandlers = new ArrayList<>();

    protected static List<CBSKeyEventHandler> globalKeyDownHandlers = new ArrayList<>();

    protected DelayedTaskHandler delayedHandler = new DelayedTaskHandler();

    private GestureDetector gestureDetector;

    protected int getDefaultStartInAnim() {
        return R.anim.cbs_slide_in_right;
    }

    protected int getDefaultStartOutAnim() {
        return R.anim.cbs_slide_out_left;
    }

    protected int getDefaultFinishInAnim() {
        return R.anim.cbs_slide_in_left;
    }

    protected int getDefaultFinishOutAnim() {
        return R.anim.cbs_slide_out_right;
    }

    protected boolean enableGesture() {
        return true;
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (enableGesture()) {
            gestureDetector = new GestureDetector(this, new MyGestureListener());
        }
        activities.add(this);
    }

    public void addResumeHandler(CBSActivityLifeCyclerHandler handler) {
        if (!resumeHandlers.contains(handler)) {
            resumeHandlers.add(handler);
        }
    }

    public void removeResumeHandler(CBSActivityLifeCyclerHandler handler) {
        if (resumeHandlers.contains(handler)) {
            resumeHandlers.remove(handler);
        }
    }

    public static void addGlobalResumeHandler(CBSActivityLifeCyclerHandler handler) {
        if (!globalResumeHandlers.contains(handler)) {
            globalResumeHandlers.add(handler);
        }
    }

    public static void removeGlobalResumeHandler(CBSActivityLifeCyclerHandler handler) {
        if (globalResumeHandlers.contains(handler)) {
            globalResumeHandlers.remove(handler);
        }
    }

    protected void onResume() {
        super.onResume();
        for (CBSActivityLifeCyclerHandler resumeHandler : resumeHandlers) {
            resumeHandler.handler(this);
        }
        for (CBSActivityLifeCyclerHandler resumeHandler : globalResumeHandlers) {
            resumeHandler.handler(this);
        }
    }

    public void addStartHandler(CBSActivityLifeCyclerHandler handler) {
        if (!startHandlers.contains(handler)) {
            startHandlers.add(handler);
        }
    }

    public void removeStartHandler(CBSActivityLifeCyclerHandler handler) {
        if (startHandlers.contains(handler)) {
            startHandlers.remove(handler);
        }
    }

    public static void addGlobalStartHandler(CBSActivityLifeCyclerHandler handler) {
        if (!globalStartHandlers.contains(handler)) {
            globalStartHandlers.add(handler);
        }
    }

    public static void removeGlobalStartHandler(CBSActivityLifeCyclerHandler handler) {
        if (globalStartHandlers.contains(handler)) {
            globalStartHandlers.remove(handler);
        }
    }

    protected void onStart() {
        super.onStart();
        for (CBSActivityLifeCyclerHandler startHandler : startHandlers) {
            startHandler.handler(this);
        }
        for (CBSActivityLifeCyclerHandler startHandler : globalStartHandlers) {
            startHandler.handler(this);
        }
    }

    public void addPauseHandler(CBSActivityLifeCyclerHandler handler) {
        if (!pauseHandlers.contains(handler)) {
            pauseHandlers.add(handler);
        }
    }

    public void removePauseHandler(CBSActivityLifeCyclerHandler handler) {
        if (pauseHandlers.contains(handler)) {
            pauseHandlers.remove(handler);
        }
    }

    public static void addGlobalPauseHandler(CBSActivityLifeCyclerHandler handler) {
        if (!globalPauseHandlers.contains(handler)) {
            globalPauseHandlers.add(handler);
        }
    }

    public static void removeGlobalPauseHandler(CBSActivityLifeCyclerHandler handler) {
        if (globalPauseHandlers.contains(handler)) {
            globalPauseHandlers.remove(handler);
        }
    }

    protected void onPause() {
        super.onPause();
        for (CBSActivityLifeCyclerHandler pauseHandler : pauseHandlers) {
            pauseHandler.handler(this);
        }
        for (CBSActivityLifeCyclerHandler pauseHandler : globalPauseHandlers) {
            pauseHandler.handler(this);
        }
    }

    public void addStopHandler(CBSActivityLifeCyclerHandler handler) {
        if (!stopHandlers.contains(handler)) {
            stopHandlers.add(handler);
        }
    }

    public void removeStopHandler(CBSActivityLifeCyclerHandler handler) {
        if (stopHandlers.contains(handler)) {
            stopHandlers.remove(handler);
        }
    }

    public static void addGlobalStopHandler(CBSActivityLifeCyclerHandler handler) {
        if (!globalStopHandlers.contains(handler)) {
            globalStopHandlers.add(handler);
        }
    }

    public static void removeGlobalStopHandler(CBSActivityLifeCyclerHandler handler) {
        if (globalStopHandlers.contains(handler)) {
            globalStopHandlers.remove(handler);
        }
    }

    protected void onStop() {
        super.onStop();
        for (CBSActivityLifeCyclerHandler stopHandler : stopHandlers) {
            stopHandler.handler(this);
        }
        for (CBSActivityLifeCyclerHandler stopHandler : globalStopHandlers) {
            stopHandler.handler(this);
        }
    }

    public void addDestroyHandler(CBSActivityLifeCyclerHandler handler) {
        if (!destroyHandlers.contains(handler)) {
            destroyHandlers.add(handler);
        }
    }

    public void removeDestroyHandler(CBSActivityLifeCyclerHandler handler) {
        if (destroyHandlers.contains(handler)) {
            destroyHandlers.remove(handler);
        }
    }

    public static void addGlobalDestroyHandler(CBSActivityLifeCyclerHandler handler) {
        if (!globalDestroyHandlers.contains(handler)) {
            globalDestroyHandlers.add(handler);
        }
    }

    public static void removeGlobalDestroyHandler(CBSActivityLifeCyclerHandler handler) {
        if (globalDestroyHandlers.contains(handler)) {
            globalDestroyHandlers.remove(handler);
        }
    }

    protected void onDestroy() {
        super.onDestroy();
        activities.remove(this);
        for (CBSActivityLifeCyclerHandler destroyHandler : destroyHandlers) {
            destroyHandler.handler(this);
        }
        for (CBSActivityLifeCyclerHandler destroyHandler : globalDestroyHandlers) {
            destroyHandler.handler(this);
        }
    }

    public void addActivityResultHandler(CBSActivityResultHandler handler) {
        if (!activityResultHandlers.contains(handler)) {
            activityResultHandlers.add(handler);
        }
    }

    public void removeActivityResultHandler(CBSActivityResultHandler handler) {
        if (activityResultHandlers.contains(handler)) {
            activityResultHandlers.remove(handler);
        }
    }

    public static void addGlobalActivityResultHandler(CBSActivityResultHandler handler) {
        if (!globalActivityResultHandlers.contains(handler)) {
            globalActivityResultHandlers.add(handler);
        }
    }

    public static void removeGlobalActivityResultHandler(CBSActivityResultHandler handler) {
        if (globalActivityResultHandlers.contains(handler)) {
            globalActivityResultHandlers.remove(handler);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        for (CBSActivityResultHandler activityResultHandler : activityResultHandlers) {
            activityResultHandler.onActivityResult(requestCode, resultCode, data);
        }
        for (CBSActivityResultHandler activityResultHandler : globalActivityResultHandlers) {
            activityResultHandler.onActivityResult(requestCode, resultCode, data);
        }
    }

    public void addKeyDownHandler(CBSKeyEventHandler handler) {
        if (!keyDownHandlers.contains(handler)) {
            keyDownHandlers.add(handler);
        }
    }

    public void removeKeyDownHandler(CBSKeyEventHandler handler) {
        if (keyDownHandlers.contains(handler)) {
            keyDownHandlers.remove(handler);
        }
    }

    public static void addGlobalKeyDownHandler(CBSKeyEventHandler handler) {
        if (!globalKeyDownHandlers.contains(handler)) {
            globalKeyDownHandlers.add(handler);
        }
    }

    public static void removeGlobalKeyDownHandler(CBSKeyEventHandler handler) {
        if (globalKeyDownHandlers.contains(handler)) {
            globalKeyDownHandlers.remove(handler);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        for (CBSKeyEventHandler keyDownHandler : keyDownHandlers) {
            if (keyDownHandler.keyEvent(keyCode, event)) {
                return true;
            }
        }
        for (CBSKeyEventHandler keyDownHandler : globalKeyDownHandlers) {
            if (keyDownHandler.keyEvent(keyCode, event)) {
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    public void startActivity(Intent intent) {
        startActivity(intent, getDefaultStartInAnim(), getDefaultStartOutAnim());
    }

    public void startActivity(Intent intent, int animin, int animout) {
        super.startActivity(intent);
        overridePendingTransition(animin, animout);
    }

    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, getDefaultStartInAnim(), getDefaultStartOutAnim());
    }

    public void startActivityForResult(Intent intent, int requestCode, int animin, int animout) {
        super.startActivityForResult(intent, requestCode);
        overridePendingTransition(animin, animout);
    }

    public void finish() {
        super.finish();
        overridePendingTransition(getDefaultFinishInAnim(), getDefaultFinishOutAnim());
    }

    public void finish(int animin, int animout) {
        super.finish();
        overridePendingTransition(animin, animout);
    }

    public void finish(boolean hasAnimation) {
        if (hasAnimation) {
            finish();
        } else {
            super.finish();
        }
    }

    // delayed task
    public void doDelayed(DelayedTask delayedTask, Bundle data, long delayedMS) {
        Message message = delayedHandler.obtainMessage(delayedTask.hashCode(), delayedTask);
        message.setData(data);
        delayedHandler.sendMessageDelayed(message, delayedMS);
    }

    public void doDelayed(DelayedTask delayedTask, Bundle data) {
        doDelayed(delayedTask, data, 0);
    }

    public void doDelayed(DelayedTask delayedTask, long delayedMS) {
        doDelayed(delayedTask, null, delayedMS);
    }

    public void doDelayed(DelayedTask delayedTask) {
        doDelayed(delayedTask, null, 0);
    }

    public void cancelDelayedTask(DelayedTask delayedTask) {
        delayedHandler.removeMessages(delayedTask.hashCode());
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (enableGesture()) {
            if (gestureDetector.onTouchEvent(ev)) {
                return true;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    protected void hideSoftInput() {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager != null) {
            if (getCurrentFocus() != null) {
                if (getCurrentFocus().getWindowToken() != null) {
                    inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
                }
            }
        }
    }

    protected void showSoftInput(View view) {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        view.requestFocus();
        if (inputMethodManager != null) {
            inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
        }
    }


    protected void exitApp() {
        for (FragmentActivity activity : activities) {
            if (activity != null) {
                activity.finish();
            }
        }
        System.exit(0);
    }

    private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            float deltaX = Math.abs(e2.getX() - e1.getX());
            float deltaY = Math.abs(e2.getY() - e1.getY());
            if (deltaX > deltaY && velocityX > 1000) {
                finish();
                return true;
            }
            return false;
        }
    }
}
